import { defineStore } from 'pinia';
import { CMutationItem } from './editorModels';

export const useMutationStore = defineStore('mutation', {
  state: () => {
    return {
      list: <CMutationItem[]>[],
      observer: <MutationObserver>{},
      index: 0,
      options:{
        'childList': true,
        'subtree': true,
        'attributes' : true,
        'characterData' : true,
        'attributeOldValue' : true,
        'characterDataOldValue' : true
      },
      isCanRedo: false,
      isCanUndo: false,
    }
  },
  getters: {

  },
  actions: {
    init(){
      this.list = []
      this.observer = new MutationObserver(this.motationCallBack);
      const target = document.getElementById('editorMain')
      this.observer.observe(target as Node, this.options)
    },
    motationCallBack(this : any, mutations: MutationRecord[], observer : MutationObserver){
      if(this.list.length > 0){
        this.list.splice(this.index + 1);
      }      
      mutations.map(function(this:any,record) {
        var target = record.target;
        console.log(record);
        //删除元素或者是添加元素;
        if( record.type === "childList" ) {
          //如果是删除元素;
          if(record.removedNodes.length !== 0) {
            //获取元素的相对索引;
            var indexs = this.getIndexs(target.childNodes , record.removedNodes );
            this.list.push({
              "undo": function() {
                this.disconnect();
                this.addChildren(record,  record.removedNodes ,indexs );
                this.reObserve();
              },
              "redo": function() {
                this.disconnect();
                this.removeChildren(record,  record.removedNodes );
                this.reObserve();
              }
            });
                        
          };
          //如果是添加元素;
          if(record.addedNodes.length !== 0) {          
            //获取元素的相对索引;
            var indexs = this.getIndexs(target.childNodes , record.addedNodes);
            this.list.push({
              "undo" : function() {
                this.disconnect();
                this.removeChildren(record, record.addedNodes);
                this.reObserve();
              },
              "redo" : function () {
                this.disconnect();
                this.addChildren(record, record.addedNodes, indexs);
                this.reObserve();
              }
            })
          };
        }else if( record.type === "characterData" ) {
          var oldValue = record.oldValue;
          var newValue = record.target.textContent //|| record.target.innerText, 不准备处理IE789的兼容，所以不用innerText了;
          this.list.push({
            "undo" : function() {
                this.disconnect();
              target.textContent = oldValue;
              this.reObserve();
            },
            "redo" : function () {
                this.disconnect();
              target.textContent = newValue;
              this.reObserve();
            }
          });
        //如果是属性变化的话style, dataset, attribute都是属于attributes发生改变, 可以统一处理;
        }else if(record.type === "attributes") {
          var oldValue = record.oldValue;        
          var attributeName = record.attributeName;
          var newValue = record.target.nodeValue
          this.list.push({
            "undo" : function() {
              this.disconnect();
              document.body.setAttribute(attributeName || '', oldValue || '')
              //target.setAttribute(attributeName, oldValue);
              this.reObserve();
            },
            "redo" : function () {
                this.disconnect();
              document.body.setAttribute(attributeName || '', newValue || '');
              
              this.reObserve();
            }
          });
        };
        //重新设置索引;
        this.index = this.list.length-1;
      })
    },
    removeChildren(record: MutationRecord, nodes : NodeList){
      for(var i= 0, len= nodes.length; i<len; i++ ) {      
        record.target.removeChild( nodes[i] );
      };  
    },
    addChildren(record : MutationRecord, nodes : NodeList, indexs : number[]){
      for(var i= 0, len= nodes.length; i<len; i++ ) {
        if(record.target.childNodes[indexs[i]]) {
          record.target.insertBefore(nodes[i], record.target.childNodes[indexs[i]])
        }else{
          record.target.appendChild(nodes[i]);
        };
      };  
    },
    indexOf(record : NodeListOf<ChildNode>, node : Node){
      return Array.prototype.indexOf.call(record, node)
    },
    getIndexs(record : NodeListOf<ChildNode>, nodes : NodeList){
      var result = [];
      for(var i = 0; i < nodes.length; i++) {
        result.push(this.indexOf(record, nodes[i]) );
      };
      return result;  
    },
    disconnect(){
      return this.observer.disconnect();  
    },
    save(obj : CMutationItem){
      if(!obj.undo)return alert("传进来的第一个参数必须有undo方法才行");
      if(!obj.redo)return alert("传进来的第一个参数必须有redo方法才行");
      this.list.push(obj);  
    },
    reset(){
      this.list = [];
      this.index = 0  
    },
    splice(index: number){
      this.list.splice(index)  
    },
    redo(){
      if(this.isCanRedo){
        this.index++;
        this.list[this.index].redo(); 
      }
    },
    undo(){
      if(this.isCanUndo){
        this.list[this.index].undo();
        this.index--;
      } 
    },
    canUndo(){
      return this.index !== -1;  
    },
    canRedo(){
      return this.list.length-1 !== this.index;
    },
    reObserve(){
      this.observer.observe(document.body, this.options)
    }
  }
});